package org.groupg.practice.document;

import java.util.Map;
import java.util.concurrent.*;

public class AsyncMetricService {
    private final DocumentStore documentStore;
    private final ExecutorService computeExecutor;
    private final BlockingQueue<MetricTask> taskQueue = new LinkedBlockingQueue<>();
    private volatile boolean running = true;

    public AsyncMetricService(DocumentStore documentStore, int computeThreads) {
        this.documentStore = documentStore;
        this.computeExecutor = Executors.newFixedThreadPool(computeThreads);

        // 启动任务调度线程
        new Thread(this::processTasks).start();
    }

    // 提交计算任务
    public void submitMetricTask(String type, String id) {
        taskQueue.offer(new MetricTask(type, id));
    }

    // 停止服务
    public void shutdown() {
        running = false;
        computeExecutor.shutdown();
    }

    // 任务处理循环
    private void processTasks() {
        while (running) {
            try {
                MetricTask task = taskQueue.take();
                computeExecutor.execute(() -> computeAndUpdate(task));
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    // 计算并更新指标
    private void computeAndUpdate(MetricTask task) {
        BusinessDocument document = documentStore.getDocument(task.type, task.id);
        if (document == null) return;

        // 模拟复杂计算
        Map<String, Object> newMetrics = computeMetrics(task.type, document);

        // 带重试的乐观锁更新
        boolean updated = false;
        int retryCount = 0;
        while (!updated && retryCount < 3) {
            updated = documentStore.updateMetrics(
                task.type,
                task.id,
                newMetrics,
                document.getVersion()
            );

            if (!updated) {
                // 刷新文档状态
                document = documentStore.getDocument(task.type, task.id);
                if (document == null) break;
                retryCount++;
                try {
                    Thread.sleep(100 * retryCount); // 指数退避
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    // 指标计算逻辑（按业务类型）
    private Map<String, Object> computeMetrics(String type, BusinessDocument document) {
        Map<String, Object> metrics = new ConcurrentHashMap<>();

        switch (type) {
            case "USER_ANALYTICS":
                metrics.put("login_count", (int) (Math.random() * 100));
                metrics.put("last_active", System.currentTimeMillis());
                metrics.put("status", "active");
                break;

            case "PRODUCT_METRICS":
                metrics.put("monthly_sales", (int) (Math.random() * 1000));
                metrics.put("customer_rating", Math.random() * 5.0);
                metrics.put("in_stock", true);
                break;

            case "FINANCIAL_REPORT":
                metrics.put("revenue", Math.random() * 1000000);
                metrics.put("profit_margin", Math.random() * 0.5);
                metrics.put("currency", "USD");
                break;
        }

        return metrics;
    }

    private record MetricTask(String type, String id) {}
}
